﻿using System;
using System.Collections;
using System.Linq;
using System.Text;
using Mighty.Common;
using System.Collections.Generic;

namespace Mighty.Brain
{
    /// <summary>
    /// 기본Brain. 모든 Brain의 기본이 되는 Brain이다. 모든 Brain은 이 클래스를 상속받아야만 한다.
    /// 게임에 관련된 모든 정보를 가지고 있는 gameInfo 속성과 게임으로부터 호출되는 11개의 함수(이벤트)로 구성되어 있다.
    /// 게임으로부터 호출되는 11개의 함수는 다음과 같다.
    /// 
    ///     GameStartEvent              : 게임시작
    ///     BettingReadyEvent           : 베팅시작, 카드를 이미 나누어 주었다
    ///     BettingTicEvent             : 베팅차례
    ///     BettingCompleteEvent        : 베팅완료, 주공이 정해졌다
    ///     ChoiceCardEvent             : (주공)카드선택, 13장의 카드중 10장의 카드선택
    ///     ChoiceFriendEvent           : (주공)프랜드선택
    ///     LastBettingEvent            : (주공)최종베팅정보, 기루다무늬변경가능
    ///     RoundReadyEvent             : 각라운드의시작
    ///     RoundTicEvent               : 카드낼차례
    ///     RoundCompleteEvent          : 각라운드의종료
    ///     GameEndEvent                : 게임의 종료
    ///     
    /// </summary>
    public class ByunBrain : BasicBrain
    {
        
        /// 각 플레이어가 가지게 되는 게임에 대한 정보, 각 이벤트가 호출되기 전에 gameInfo에는 항상 최신의 정보가
        /// 업데이트되어 있다
        

        public bool betting_possble;
        public int Max_shape = 0;
        public int[] shap_count = new int[5];
        public int[,] myCard = new int[5, 16];
        public int[] shap_sum = new int[5];
        
        /// 게임시작. 매 게임마다 초기화해야할 코드가 있다면 여기에 넣어라



        public override void GameStartEvent()
        {
        }
        
        /// 베팅시작, 카드를 나누어 주고 호출된다. gameInfo.myCards를 참고

           

        public override void BettingReadyEvent()
        {

            
            int i;

            ///4(모양)X15(번호)행렬로
            for (i = 0; i < 10; i++)
            {
                HandedCard c = (HandedCard) gameInfo.myCards[i];
                int s = (int)c.shape;
                myCard[s, c.number] = 1;
            }


             //많이 가진 무늬찾기. 만약 무늬 개수가 같으면 모양별 점수를 비교
            
            
            for (int t = 0; t < 5; t++)
            {
                for (int j = 0; j < 16; j++ )
                {
                    if (myCard[t, j] != 0)
                    {
                        shap_count[t]++; //자기가 가진 카드들을 모양별로 개수를 센다. 
                        
                        if (j < 8)//모양별 카드를 점수화 한것 을 더하여 어떤 모양의 숫자가 가장 큰지 정한다.  
                            shap_sum[t] = shap_sum[t] + 1;
                        else if(j<12)
                            shap_sum[t] = shap_sum[t] + 5;
                        else if (j < 16)
                            shap_sum[t] = shap_sum[t] + 10;
                    }
                }
            }

            ///shap_sum은 카드별 점수
            int Max_Card = shap_sum[0]; //일단 가장 많은 모양 카드를 'shap_sum[0](clover)라 함.'
            
            for (int v = 1; v < 4; v++)
            {
                if (shap_sum[v] > Max_Card)
                {
                    Max_Card = shap_sum[v];
                    Max_shape = v;//(많은 모양 카드을 알기 위한 변수)
                }
            }
            

            if (shap_count[Max_shape] > 3) //  정해진 카드가 4장 이상 
            {
                /// 'i'모양으로 배팅부르기 시작한다.
                if(shap_sum[Max_shape]>13)
                betting_possble = false;
                
            }
            else
            {
                ///  배팅하지 않고 pass한다.
                betting_possble = true; 
            }       
        

        }

        
        /// 베팅차례, 지금까지 배팅된 정보(gameInfo.bettingHistory)를 참고하여 베팅을 결정한다

        public override Betting BettingTicEvent()
        {
            Betting betting = new Betting();
            Betting previousBetting = gameInfo.betting;

            betting.isPass = betting_possble;
           // if (betting.isPass == betting_possble)
            
                if (Max_shape == 0)
                {
                    betting.giruda = Giruda.Clover;
                }
                else if (Max_shape == 1)
                {
                    betting.giruda = Giruda.Diamond;
                }
                else if (Max_shape == 2)
                {
                    betting.giruda = Giruda.Spade;
                }
                else if (Max_shape == 3)
                {
                    betting.giruda = Giruda.Heart;
                }

                for (int i = 0; i < 10; i++)
                {
                    HandedCard d = (HandedCard)gameInfo.myCards[i];
                    int n = (int)d.shape;
                    myCard[n, d.number] = 1;
                }

                int s_num = Max_shape;

                int zero_seven = 0;
                for (int k = 1; k < 8; k++)
                {
                    if (myCard[s_num, k] != 0)
                    {
                        zero_seven++; //0~7까지의 개수 개수를 구함
                    }
                }

                int eight_eleven = 0;
                for (int k = 8; k < 12; k++)
                {
                    if (myCard[s_num, k] != 0)
                    {
                        eight_eleven++; //8~11까지의 개수 개수를 구함
                    }
                }

                int twelve_fifteen = 0;
                for (int k = 12; k < 16; k++)
                {
                    if (myCard[s_num, k] != 0)
                    {
                        twelve_fifteen++; //11~15까지의 개수 개수를 구함
                    }
                }

                int q = zero_seven;

                switch (q)
                {
                    case 2:
                        {
                            if (eight_eleven + twelve_fifteen >= 5)
                            {
                                if (previousBetting.limit < 17)
                                {
                                    betting.limit = previousBetting.limit + 1;
                                }
                            }

                            else if (eight_eleven + twelve_fifteen >= 3)
                            {
                                if (previousBetting.limit < 14)
                                {
                                    betting.limit = previousBetting.limit + 1;
                                }
                            }
                        }
                        break;

                    case 3:
                        {
                            if (eight_eleven + twelve_fifteen >= 4)
                            {
                                if (previousBetting.limit < 17)
                                {
                                    betting.limit = previousBetting.limit + 1;
                                }
                            }

                            else if (eight_eleven + twelve_fifteen >= 2)
                            {
                                if (previousBetting.limit < 14)
                                {
                                    betting.limit = previousBetting.limit + 1;
                                }
                            }
                        }
                        break;

                    case 4:
                        {
                            if (eight_eleven + twelve_fifteen >= 3)
                            {
                                if (previousBetting.limit < 16)
                                {
                                    betting.limit = previousBetting.limit + 1;
                                }
                            }

                            else if (eight_eleven + twelve_fifteen >= 1)
                            {
                                if (previousBetting.limit < 14)
                                {
                                    betting.limit = previousBetting.limit + 1;
                                }
                            }
                        }
                        break;

                    case 5:
                        {
                            if (eight_eleven + twelve_fifteen >= 2)
                            {
                                if (previousBetting.limit < 16)
                                {
                                    betting.limit = previousBetting.limit + 1;
                                }
                            }

                            else if (eight_eleven + twelve_fifteen >= 0)
                            {
                                if (previousBetting.limit < 14)
                                {
                                    betting.limit = previousBetting.limit + 1;
                                }
                            }
                        }
                        break;

                    case 6:
                        {
                            if (eight_eleven + twelve_fifteen >= 2)
                            {
                                if (previousBetting.limit < 16)
                                {
                                    betting.limit = previousBetting.limit + 1;
                                }
                            }

                            else if (eight_eleven + twelve_fifteen >= 0)
                            {
                                if (previousBetting.limit < 14)
                                {
                                    betting.limit = previousBetting.limit + 1;
                                }
                            }
                        }
                        break;
                }


                return betting;
           // }
        }


        /// <summary>
        /// 베팅완료, 주공이 정해졌다. 베팅이 끝났을 경우 처리할 코드가 있다면 여기에 하라.
        /// </summary>
        public override void BettingCompleteEvent()
        {
        }

        /// <summary>
        /// (주공)카드선택, 13장의 카드중 10장의 카드선택. 버릴3장의 카드에 cmdRemove=true로 설정해주어야 한다
        /// 만약 정확히 3장의 카드가 선택되지 않았을 경우에는 새로추가된 3장의 카드가 그대로 버려진다.
        /// ChoiceCardEvent 가 호출된 후에는 선택된 10장의 카드는 myCards[0]부터 차례대로 배치되고 버려진 3장의 카드는
        /// myCards[10]에서부터 배치되어 나중에 어떤 카드가 버려졌는지 알수 있게 해준다
        /// </summary>
        /// <remarks>
        /// [기본행동] 추가된 3장의 카드를 그대로 버린다
        /// </remarks>
        public override HandedCard[] ChoiceCardEvent()
        {

            int u = 0;
            int Mini_shapeCard = shap_count[0];//가장 작은 수의 카드 모양
            int Mini_num = 0;
            int remove_count = 0;
            for (u = 1; u < 4; u++)
            {
                if (Mini_shapeCard > shap_count[u])
                {
                    Mini_shapeCard = shap_count[u];
                    Mini_num = u;
                }
            }
            switch (u)
            {
                case 0:
                    {
                        for (int n = 0; n < 14; n++)
                        {
                            if (gameInfo.myCards[n].shape == Shape.Clover)
                            {
                                gameInfo.myCards[n].cmdRemove = true;
                                remove_count++;
                                if (gameInfo.myCards[n].number > 12)
                                {
                                    gameInfo.myCards[n].cmdRemove = false;
                                    remove_count--;
                                }

                            }
                            if (remove_count == 3)
                                break;
                        }

                    } break;
                case 1:
                    {
                        for (int n = 0; n < 14; n++)
                        {
                            if (gameInfo.myCards[n].shape == Shape.Diamond)
                            {
                                gameInfo.myCards[n].cmdRemove = true;
                                remove_count++;
                                if (gameInfo.myCards[n].number > 12)
                                {
                                    gameInfo.myCards[n].cmdRemove = false;
                                    remove_count--;
                                }
                            }
                            if (remove_count == 3)
                                break;
                        }

                    } break;
                case 2:
                    {
                        for (int n = 0; n < 14; n++)
                        {
                            if (gameInfo.myCards[n].shape == Shape.Spade)
                            {
                                gameInfo.myCards[n].cmdRemove = true;
                                remove_count++;
                                if (gameInfo.myCards[n].number > 12)
                                {
                                    gameInfo.myCards[n].cmdRemove = false;
                                    remove_count--;
                                }
                            }
                            if (remove_count == 3)
                                break;
                        }

                    } break;
                case 3:
                    {
                        for (int n = 0; n < 14; n++)
                        {
                            if (gameInfo.myCards[n].shape == Shape.Heart)
                            {
                                gameInfo.myCards[n].cmdRemove = true;
                                remove_count++;
                                if (gameInfo.myCards[n].number > 12)
                                {
                                    gameInfo.myCards[n].cmdRemove = false;
                                    remove_count--;
                                }
                            }
                            if (remove_count == 3)
                                break;
                        }

                    } break;

            }

            while (remove_count < 3)
            {
                for (int c = 0; c < 13; c++)
                {
                    if (gameInfo.myCards[c].cmdRemove == false)
                    {
                        if((int)gameInfo.myCards[c].shape == (int)gameInfo.betting.giruda)
                        {
                            if (gameInfo.myCards[c].number < 5)
                                gameInfo.myCards[c].cmdRemove = true;
                        }
                    }
                    
                }

            }

            return gameInfo.myCards;
        }
            

        /// <summary>
        /// (주공)프랜드선택. 프랜드를 선택하는 방법은 노프랜드(FriendPlayer.HowToSelect.nofriend),
        /// 초구프랜드(FriendPlayer.HowToSelect.firstwin),카드프랜드(FriendPlayer.HowToSelect.card)가 있다.
        /// </summary>
        /// <remarks>
        /// [기본행동] 초구프랜드를 선택한다
        /// </remarks>
        public override FriendPlayer ChoiceFriendEvent()
        {
            gameInfo.friend.howToSelect = FriendPlayer.HowToSelect.firstwin;
            return gameInfo.friend;
        }

        
        public override Betting LastBettingEvent()
        {
            return gameInfo.betting;
        }

        /// <summary>
        /// 각라운드의시작, 매라운드마다 초기화할 코드가 있다면 이부분에 들어가게 된다
        /// </summary>
        public override void RoundReadyEvent()
        {

        }

        /// <summary>
        /// 카드낼차례, 각 사용자의 턴에 한번씩 호출되며 낼 카드를 결과값으로 리턴해야 한다. 사용가능한 카드에는 
        /// myCards[i].isPossible 속성이 true로 설정되어 있다. 만약 사용불가능한 카드를 낼 경우에 시스템은 카드배열에서 
        /// 제일 처음 만나는 사용가능한 카드를 골라서 사용한다
        /// </summary>
        /// <remarks>
        /// [기본행동] 가능한 카드중에서 랜덤하게 하나의 카드를 선택한다
        /// </remarks>
        public override HandedCard RoundTicEvent()
        {
            ArrayList possibleCards = new ArrayList();
            foreach (HandedCard card in gameInfo.myCards)
            {
                if (card.isPossible) possibleCards.Add(card);
            }

            Random r = new Random();
            int k = r.Next(possibleCards.Count);

            return (HandedCard)possibleCards[k];
        }

        /// <summary>
        /// 각라운드의종료, 각 라운드가 종료되면 호출된다. 각 라운드의 승자는 gameinfo의 winner를 참조한다
        /// </summary>
        public override void RoundCompleteEvent()
        {

        }

        /// <summary>
        /// 게임의 종료, 게임이 종료되었을때 실행될 코드는 여기에 추가한다.
        /// </summary>
        public override void GameEndEvent()
        {

        }
    }
}
